home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_01_04 / 1n04018a < prev    next >
Text File  |  1990-07-17  |  10KB  |  270 lines

  1. /*
  2. **  Figure 3 - POSIX-style directory processing
  3. */
  4.  
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <dos.h>
  8. #include <io.h>
  9. #include <errno.h>
  10. #include "dirent.h"
  11.  
  12. #define _NDIRS 20
  13. #define SUCCESS 0
  14. #define ERROR  -1
  15.  
  16. #define LAST_CHAR(s) ((char *)(s))[strlen(s) - 1]
  17.  
  18. int DFerr;
  19. DOS_DIR _DIRS[_NDIRS];  /* Initilize DOS_DIR array to zeros     */
  20.  
  21. /*
  22. **  Convert Unix-style pathnames to DOS-style
  23. */
  24.  
  25. static char *unix2dos(char *path)
  26. {
  27.         char *p;
  28.  
  29.         while (NULL != (p = strchr(path, '/')))
  30.                 *p = '\\';
  31.         return path;
  32. }
  33.  
  34. /****************************************************************/
  35. /*                                                              */
  36. /*  opendir()                                                   */
  37. /*                                                              */
  38. /*  Function: Open a directory for reading.                     */
  39. /*                                                              */
  40. /*  Parameters: 1 - Directory name. May include path spec.      */
  41. /*                                                              */
  42. /*  Returns: Pointer to a DOS_DIR typedef'ed structure, similar */
  43. /*           to fopen() returning a FILE pointer.               */
  44. /*                                                              */
  45. /*           NULL if error, DFerr set as follows:               */
  46. /*           SUCCESS - No error                                 */
  47. /*           ENOENT  - Could not locate directory or contents   */
  48. /*           ENOTDIR - Not a directory                          */
  49. /*           ENOMEM  - Too many directories already open        */
  50. /*                                                              */
  51. /*  Side effects: The dd_size element of the DOS_DIR structure  */
  52. /*                will contain a number representing the total  */
  53. /*                number of entries in the directory. The       */
  54. /*                dd_loc element will be set to zero since      */
  55. /*                no elements have, as yet, been read.          */
  56. /*                                                              */
  57. /****************************************************************/
  58.  
  59. DOS_DIR *opendir(char *fname)
  60. {
  61.         int i;
  62.         unsigned n = 0;
  63.         char nametmp[13], *p;
  64.         struct DSTRUCT dstruct;
  65.  
  66.         for (i = 0; i < _NDIRS; ++i)
  67.         {
  68.                 if (!_DIRS[i].dd_fd)
  69.                         break;
  70.         }
  71.         if (_NDIRS <= i)
  72.         {
  73.                 DFerr = ENOMEM;
  74.                 return NULL;
  75.         }
  76.  
  77.         unix2dos(fname);
  78.         if (':' == fname[1] && 1 < strlen(fname))
  79.                 p = &fname[2];
  80.         else    p = fname;
  81.         while ('\\' == LAST_CHAR(p) && 1 < strlen(p))
  82.                 LAST_CHAR(p) = '\0';
  83.         
  84.         if (strcmp(p, "\\") && strlen(p))
  85.         {
  86.                 if (NULL == (rfind_1st(fname, FA_ANY, &_DIRS[i].dd_buf)))
  87.                 {
  88.                         DFerr = ENOENT;
  89.                         return NULL;
  90.                 }
  91.                 if (!(FA_DIREC & _DIRS[i].dd_buf.ATTRIBUTE))
  92.                 {
  93.                         DFerr = ENOTDIR;
  94.                         return NULL;
  95.                 }
  96.         }
  97.         strcpy(_DIRS[i].dd_dirname, fname);
  98.         if (!strlen(p))
  99.                 strcat(_DIRS[i].dd_dirname, ".");
  100.         if ('\\' != LAST_CHAR(_DIRS[i].dd_dirname))
  101.                 strcat(_DIRS[i].dd_dirname, "\\");
  102.         strcat(strupr(_DIRS[i].dd_dirname), "*.*");
  103.         if (NULL == rfind_1st(_DIRS[i].dd_dirname, FA_ANY, &_DIRS[i].dd_buf))
  104.         {
  105.                 DFerr = ENOENT;
  106.                 return NULL;
  107.         }
  108.         memcpy(&dstruct, &_DIRS[i].dd_buf, sizeof(struct DSTRUCT));
  109.         do
  110.         {
  111.                 ++n;
  112.         } while (rfind_nxt(&_DIRS[i].dd_buf));
  113.         memcpy(&_DIRS[i].dd_buf, &dstruct, sizeof(struct DSTRUCT));
  114.         _DIRS[i].dd_size = n;
  115.         _DIRS[i].dd_loc  = 0;
  116.         _DIRS[i].dd_fd   = i + 1;
  117.         DFerr = SUCCESS;
  118.         return &_DIRS[i];
  119. }
  120.  
  121. /****************************************************************/
  122. /*                                                              */
  123. /*  closedir()                                                  */
  124. /*                                                              */
  125. /*  Function: Close a preeviously opened directory.             */
  126. /*                                                              */
  127. /*  Parameters: 1 - DOS_DIR pointer of directory to close.      */
  128. /*                                                              */
  129. /*  Returns: SUCCESS or ERROR.                                  */
  130. /*                                                              */
  131. /****************************************************************/
  132.  
  133. int closedir(DOS_DIR *dirp)
  134. {
  135.         if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  136.         {
  137.                 DFerr = EBADF;
  138.                 return ERROR;
  139.         }
  140.         memset(dirp, 0, sizeof(DOS_DIR));
  141.         return SUCCESS;
  142. }
  143.  
  144. /****************************************************************/
  145. /*                                                              */
  146. /*  rewinddir()                                                 */
  147. /*                                                              */
  148. /*  Function: Reset an open DOS_DIR to its first entry.         */
  149. /*                                                              */
  150. /*  Parameters: 1 - DOS_DIR pointer of directory to rewind.     */
  151. /*                                                              */
  152. /*  Returns: SUCCESS or ERROR.                                  */
  153. /*                                                              */
  154. /****************************************************************/
  155.  
  156. int rewinddir(DOS_DIR *dirp)
  157. {
  158.         if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  159.         {
  160.                 DFerr = EBADF;
  161.                 return ERROR;
  162.         }
  163.         rfind_1st(dirp->dd_dirname, FA_ANY, &(dirp->dd_buf));
  164.         dirp->dd_loc = 0;
  165.         return SUCCESS;
  166. }
  167.  
  168. /****************************************************************/
  169. /*                                                              */
  170. /*  seekdir()                                                   */
  171. /*                                                              */
  172. /*  Function: Point to a selected entry in a DOS_DIR.           */
  173. /*                                                              */
  174. /*  Parameters: 1 - DOS_DIR pointer of directory to rewind.     */
  175. /*              2 - Offset of entry to seek                     */
  176. /*              3 - Origin of offset                            */
  177. /*                                                              */
  178. /*  Returns: A DSTRUCT pointer, same as returned by rfind_1st() */
  179. /*           and rfind_nxt().                                   */
  180. /*                                                              */
  181. /*           NULL if error, DFerr set as follows:               */
  182. /*           SUCCESS - No error                                 */
  183. /*           EBADF   - Bad file (DOS_DIR) pointer               */
  184. /*           EACCES  - Illegal origin specification             */
  185. /*           EOF     - Attempt to seek past end of directory    */
  186. /*                                                              */
  187. /****************************************************************/
  188.  
  189. struct DSTRUCT *seekdir(DOS_DIR *dirp, int offset, int origin)
  190. {
  191.         int i, loc;
  192.  
  193.         if (0 == dirp->dd_fd || _NDIRS < dirp->dd_fd)
  194.         {
  195.                 DFerr = EBADF;
  196.                 return NULL;
  197.         }
  198.         switch (origin)
  199.         {
  200.         case SEEK_SET:
  201.                 loc = offset + 1;
  202.                 break;
  203.         case SEEK_CUR:
  204.                 loc = dirp->dd_loc + offset;
  205.                 break;
  206.         case SEEK_END:
  207.                 loc = dirp->dd_size + offset;
  208.                 break;
  209.         default:
  210.                 DFerr = EACCES;
  211.                 return NULL;
  212.         }
  213.         
  214.         if (loc > (int)dirp->dd_size